import { useState, useEffect, createRef, useRef, Component, forwardRef, useImperativeHandle } from 'react'

/* 
// 创建子组件「类」
class Child extends Component {
    spanBox = createRef()
    state = {
        x: 100
    }
    submit = () => { }
    render() {
        return <div className="child-box">
            <span ref={this.spanBox}>我是子组件</span>
        </div>
    }
} 
*/

// 创建子组件「函数」
const Child = forwardRef(
    function Child(props, ref) {
        // 基于 useImperativeHandle 这个Hook函数，可以把函数类型子组件内部的某些东西返回，赋值给转发过来的REF对象中的current属性！！
        useImperativeHandle(ref, () => {
            return {
                n: 100,
                m: 200
            }
        })
        return <div className="child-box">
            {/* <span ref={ref}>我是子组件</span> */}
            <span>我是子组件</span>
        </div>
    }
)

// 父组件
export default function Demo() {
    let children = useRef()
    useEffect(() => {
        console.log(children.current)
    }, [])
    return <div>
        <Child x="10" ref={children} />
    </div>

    /* 
    @1 给类组件类型的子组件设置ref，其目的是获取子组件实例「这样想操作子组件中的哪些东西，在子组件内部，就把这些东西挂载到实例上即可」
    @2 给函数类型的子组件设置ref，默认是报错的 Warning: Function components cannot be given refs ... Did you mean to use React.forwardRef()?
        + 我们需要把函数子组件，基于 React.forwardRef 进行处理，实现“REF的转发”「就是把调用子组件的时候，设置的属性(包含ref属性)，都作为实参传递给子组件」
            const Child = forwardRef(
                function Child(props, ref) {
                ...
                }
            )
        + 此时在子组件内部，如果我们把转发的REF值，赋值给子组件的某个元素的ref属性，这样在父组件中就可以直接获取到子组件这个元素的真实DOM了
        + 在子组件内部，还可以基于 useImperativeHandle 这个API，把子组件内部的某些内容直接返回，这样在父组件中也就可以调用这些信息！
    */
}